package com.example.demo50rolehierarchy.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 举个简单的例子，假设角色层次结构是 ROLE_A > ROLE_B > ROLE_C，现在直接给用户分配的权限是 ROLE_A，但实际上用户拥有的权限有 ROLE_A、ROLE_B 以及 ROLE_C。
     *
     * RoleHierarchyImpl#buildRolesReachableInOneStepMap 和 RoleHierarchyImpl#buildRolesReachableInOneOrMoreStepsMap 解析 ROLE_admin > ROLE_user
     *
     * RoleHierarchyImpl#getReachableGrantedAuthorities 根据当前角色，返回当前角色真正可访问的角色信息
     * RoleHierarchyImpl#getReachableGrantedAuthorities 方法将在 RoleHierarchyVoter 投票器中被调用。
     */
    @Bean
    RoleHierarchy roleHierarchy() {
        RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
        roleHierarchy.setHierarchy("ROLE_admin > ROLE_user");
        return roleHierarchy;
    }

    @Override
    @Bean
    protected UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager us = new InMemoryUserDetailsManager();
        us.createUser(User.withUsername("wangnian").password("{noop}123").roles("admin").build());
        us.createUser(User.withUsername("zhangsan").password("{noop}123").roles("user").build());
        return us;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**").hasRole("admin")
                .antMatchers("/user/**").hasRole("user")
                .anyRequest().authenticated()
                .and().formLogin()
                .and().csrf().disable();
    }
}
